<script setup lang="ts">
/**
 * @name CalculationStatusMonitoring
 * @description 计算状态监控
 */
import type { ComponentExposed } from 'vue-component-type-helpers'
import { ElTooltip } from 'element-plus'
import {
  LogModal,
  RelationshipModal,
  SearchForm,
} from './components'
import type { TableDataItem } from './type.d'
import {
  defaultColumns,
  defaultPagingParams,
} from './index'
import type {
  CalculationStatusMonitoringSelectCalculationStatusPageResult1 as A,
  CalculationStatusMonitoringSelectCalculationStatusPageResult2 as B,
  CalculationStatusMonitoringPublicParams,
  CalculationStatusMonitoringUpdateDataByOneselfParams,
  DictionaryEncoInfo,
  TableColumn,
} from '@/types'
import type { ContextMenuData } from '@/components/type'
import { calculationStatusMonitoringApi } from '@/api'
import IndicatorDataCurveModal from '@/components/IndicatorDataCurveModal/IndicatorDataCurveModal.vue'
import { getDefaultTimes } from '@/components/IndicatorDataCurveModal/composable'
import { STORAGE_MODES } from '@/enum/modules/indicator'
// ------------------use------------------
// #region

const isDev = process.env.NODE_ENV === 'development'

const { $message, $prompt } = useCurrentInstance()
const { withLoading, loading } = useDefineLoading()
const [tableData, setTableData] = useState<TableDataItem[]>(
  [],
)
const [selectIndicatorInfo, setSelectIndicatorInfo]
  = useState<A['baseDataValInternalList'][number] | null>(
    null,
  )
const [total, setTotal] = useState<number>(0)
// 右键菜单显示与否
const [isRightMenu, setIsRightMenu]
  = useState<boolean>(false)
const [columns, setColumns] = useShallowState<
  TableColumn<any>[]
>([...defaultColumns])
// 右键菜单位置
const [rightMenuPosition, setRightMenuPosition] = useState({
  x: 0,
  y: 0,
})
const [rightMenuCell, setRightMenuCell]
  = useState<null | HTMLTableCellElement>(null)
const [timeTypeOptions, setTimeTypeOptions] = useState<
  DictionaryEncoInfo[]
>([])

/** 存贮原始数据 */
const tableDataSource: Map<
  string,
  A['baseDataValInternalList'][number]
> = new Map()

const logModalRef
  = ref<ComponentExposed<typeof LogModal>>()
const relationshipModalRef
  = ref<ComponentExposed<typeof RelationshipModal>>()
const searchRef
  = ref<ComponentExposed<typeof SearchForm>>()
const pagingParams = ref({
  ...defaultPagingParams,
})
const contextMenuData = ref<Partial<ContextMenuData>[]>([
  {
    label: '自定义值',
    onClick: handleA,
  },
  {
    label: '重新计算',
    onClick: handleB,
  },
  {
    label: '指标计算关系图',
    disabled: false,
    onClick: handleC,
  },
  {
    label: '查看执行过程',
    onClick: handleD,
  },
])

const timeType = computed(() => {
  return pagingParams.value.key as STORAGE_MODES
})

onBeforeMount(() => {
  getTimeTypeOptions()
})

// function changeRelationshipState(bol: boolean) {
//   contextMenuData.value[2]!.disabled = bol
// }
async function getTableData() {
  const isValid = await searchRef?.value?.validate()
  if (!isValid)
    return
  const { data: res } = await withLoading(
    calculationStatusMonitoringApi.selectCalculationStatusPage,
  )(pagingParams.value)
  const { total, records } = res
  handleTableData(records)
  handleColumn()
  setTotal(total)
  setSelectIndicatorInfo(null)
}
function handleTableData(data: A[] | B[]) {
  tableDataSource.clear()
  const arr: TableDataItem[] = []
  if (pagingParams.value.key === '0m') {
    arr.push(...(data as B[]))
  }
  else {
    for (const item of data as A[]) {
      const {
        baseDataValInternalList,
        indicatorName,
        indicatorNumber,
      } = item
      const o: TableDataItem = {
        indicatorName,
        indicatorNumber,
      }
      for (const son of baseDataValInternalList) {
        // ! 存贮数据，便于后续查找使用
        const { dataTime, state, dataValue } = son

        let _dataTime = dataTime
        if (pagingParams.value.key === '1H') {
          _dataTime = `${_dataTime}:00`
        }
        const key = `${indicatorNumber}@${_dataTime}`
        tableDataSource.set(key, {
          ...son,
          indicatorNumber,
          indicatorName,
        })
        // 展开数据
        o[_dataTime] = !state
          ? ''
          : state === 0
            ? '未处理'
            : state === 1
              ? dataValue ?? ''
              : '失败'
      }
      arr.push(o)
    }
  }
  setTableData(arr)
}
function handleColumn() {
  if (tableData.value.length === 0) {
    setColumns([...defaultColumns])
    return
  }
  const column = Object.keys(tableData.value[0]!).filter(
    str => /^\d+/.test(str),
  )

  const { key } = unref(pagingParams)
  const _column: TableColumn<any>[] = []
  if (key === '0m') {
    _column.push({
      key: uuid(),
      label: '实时值',
      render: ({ row }) => row.dataValue != null && row.dataTime
        ? h(
          ElTooltip,
          {
            placement: 'top',
            content: row.dataTime,
          },
          () => h(
            ElLink,
            { type: 'primary', onClick: () => clickValue(row.indicatorNumber) },
            () => h('code', row.dataValue),
          ),
        )
        : h('code', '-'),
    })
  }
  else {
    _column.push(
      ...column.map(str => ({
        key: uuid(),
        label: str,
        prop: str,
        render: ({ row }: any) => {
          const val = row[str]
          if (val === '失败') {
            // ! 获取当前时间段信息
            const key = `${row?.indicatorNumber}@${str}`
            const info = tableDataSource.get(key)!
            return h(
              ElTooltip,
              {
                content: info.errMsg ?? '前置条件错误',
                placement: 'top',
              },
              {
                default: () => val,
              },
            )
          }
          if (val != null) {
            return h(
              ElLink,
              { type: 'primary', onClick: () => clickValue(row.indicatorNumber) },
              () => h('code', val),
            )
          }
          return val
        },
      })),
    )
  }
  setColumns([...defaultColumns, ..._column])
}
function handleCellClassName({ column }: any) {
  if (
    [
      '操作',
      '实时值',
      '指标编码',
      '指标名称',
      '序号',
    ].includes(column.label)
  ) {
    return ''
  }

  return 'cell'
}
function handleContextmenuHide() {
  rightMenuCell.value?.classList?.remove?.('select')
}
async function handleCellContextmenu(data: any, column: any, cell: HTMLTableCellElement, event: PointerEvent) {
  if (
    [
      '操作',
      '实时值',
      '指标编码',
      '指标名称',
      '序号',
    ].includes(column.label)
  ) {
    return
  }

  // ! 获取当前时间段信息
  const key = `${data?.indicatorNumber}@${column.label}`
  const info = tableDataSource.get(key)!
  setSelectIndicatorInfo(info)
  // changeRelationshipState(!data[column.label]);
  setRightMenuCell(cell)
  cell.classList.add('select')
  setRightMenuPosition({
    x: event.clientX,
    y: event.clientY,
  })
  await nextTick()
  setIsRightMenu(true)
}
async function getTimeTypeOptions() {
  const { data } = await sysDictionaryEncoApi.queryList(
    'SHI_JIAN_KE_LI',
  )
  setTimeTypeOptions(data)
}
/** 自定义值 */
async function handleA() {
  const { dataTime, id, indicatorNumber, dataValue }
    = unref(selectIndicatorInfo)!
  const inputValue = !dataValue ? '' : dataValue.toString()
  const res = await $prompt('自定义值', '修改', {
    inputPattern: /^\d+(\.\d+)?$/,
    inputErrorMessage: '请输入数字！',
    inputValue,
  })

  const params: CalculationStatusMonitoringUpdateDataByOneselfParams
    = {
      dataTime,
      val: +res.value,
      indicatorNumber: indicatorNumber as string,
      key: pagingParams.value.key!,
    }
  if (id) {
    params.id = id
  }
  await withLoading(
    calculationStatusMonitoringApi.updateDataByOneself,
  )(params)
  $message.success('数据更新成功！')
  getTableData()
}
/** 重新计算 */
async function handleB() {
  const { dataTime, indicatorNumber, indicatorName }
    = unref(selectIndicatorInfo)!
  const params: CalculationStatusMonitoringPublicParams = {
    dataTime,
    indicatorNumber: indicatorNumber as string,
    key: pagingParams.value.key!,
    indicatorName: indicatorName as string,
  }
  calculationStatusMonitoringApi.reCalculation(params)
  $message.success('重新计算已发起！')
}
/** 指标计算关系图 */
async function handleC() {
  relationshipModalRef.value?.open()
}
/** 查看执行过程 */
async function handleD() {
  logModalRef.value?.open()
}
function handleClickNode(row: any) {
  pagingParams.value.pointId = row.id
  getTableData()
}

const indicatorDataCurveModalRef = ref<InstanceType<typeof IndicatorDataCurveModal>>()
const indicatorNumber = ref<string>()
async function clickValue(code: string) {
  indicatorNumber.value = code
  await nextTick()
  indicatorDataCurveModalRef.value?.showModal()
}
// #endregion
</script>

<template>
  <div class="padding-sm flex container">
    <ReadonlyPointTree
      fire
      class="flex-incompressible"
      @click-node="handleClickNode"
    />
    <div
      class="flex-direction flex-fillRemaining margin-left-sm overflow flex align-end"
    >
      <view-table
        :loading="loading"
        :columns="columns"
        :data="tableData"
        border
        row-key="indicatorNumber"
        :show-download="isDev"
        :cell-class-name="handleCellClassName"
        @cell-contextmenu="handleCellContextmenu"
      >
        <template #actions>
          <SearchForm
            ref="searchRef"
            v-model="pagingParams"
            @search="getTableData"
            @reset="getTableData"
          />
        </template>
      </view-table>

      <!-- 分页 -->
      <ListsPagination
        v-model:page-num="pagingParams.pageNumber"
        v-model:page-size="pagingParams.pageSize"
        :total="total"
        @current-change="getTableData"
        @size-change="getTableData"
      />
    </div>
    <LogModal
      ref="logModalRef"
      :date-type="pagingParams.key!"
      :info="selectIndicatorInfo"
    />
    <RelationshipModal
      ref="relationshipModalRef"
      :time-type-options="timeTypeOptions"
      :date-type="pagingParams.key!"
      :info="selectIndicatorInfo"
    />
    <ContextMenu
      v-model="isRightMenu"
      :data="contextMenuData"
      :position="rightMenuPosition"
      @hide="handleContextmenuHide"
    />

    <!-- 指标数据折线图 -->
    <IndicatorDataCurveModal
      v-if="indicatorNumber"
      ref="indicatorDataCurveModalRef"
      :title="
        timeType !== STORAGE_MODES.NOW
          ? '指标数据折线图'
          : '实时数据折线图'
      "
      :indicator-number="indicatorNumber"
      :initial-time-type="timeType"
      v-bind="getDefaultTimes(timeType)"
    />
  </div>
</template>

<style lang="scss" scoped>
//------------------组件样式------------------
//-------------样式穿透-------------
</style>
